package com.botarena.server.servlets.rpc;

import java.util.LinkedList;
import java.util.List;

import javax.jdo.JDOObjectNotFoundException;

import com.botarena.client.contest.remote.ContestAccess;
import com.botarena.server.model.Account;
import com.botarena.server.model.Bot;
import com.botarena.server.model.Contest;
import com.botarena.server.services.AccountService;
import com.botarena.server.services.ContestService;
import com.botarena.shared.ContestInfo;
import com.botarena.shared.ContestState;
import com.botarena.shared.RankInfo;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

public class ContestAccessServlet extends RemoteServiceServlet implements
		ContestAccess {

	private static final long serialVersionUID = 6672413398504669163L;
	private final ContestService contestService;
	private final AccountService accountService;

	public ContestAccessServlet() {
		contestService = new ContestService();
		accountService = new AccountService();
	}

	@Override
	public ContestState getContestState(String key) {

		Contest contest = getContest(KeyFactory.stringToKey(key));

		ContestState state = new ContestState(contest.getName(), contest
				.getFrom(), contest.getTo(), contestService.botNum(),
				contestService.userNum());

		return state;
	}

	@Override
	public List<ContestInfo> getAllContests() {

		List<Contest> contests = contestService.getAllContests();

		List<ContestInfo> results = new LinkedList<ContestInfo>();
		for (Contest contest : contests) {
			results.add(new ContestInfo(KeyFactory
					.keyToString(contest.getKey()), contest.getName(), contest
					.getFrom(), contest.getTo()));
		}

		return results;
	}

	@Override
	public List<RankInfo> getRanking(String key, int size) {

		List<Bot> bots = contestService.getRanking(key, size);

		List<RankInfo> rank = new LinkedList<RankInfo>();

		int pos = 0;
		for (Bot bot : bots) {
			if (pos < size)
				rank.add(prepareRankInfo(bot, pos));
			else
				rank.add(prepareEmpty(bot, pos));
			pos++;
		}

		return rank;
	}

	@Override
	public List<RankInfo> getRankPart(List<String> botKeys) {
		List<Bot> bots = contestService.getRankingPart(botKeys);
		List<RankInfo> rank = new LinkedList<RankInfo>();

		int pos = 0;
		for (Bot bot : bots) {
			rank.add(prepareRankInfo(bot, pos));
			pos++;
		}

		return rank;
	}

	@Override
	public List<RankInfo> getRankTop(String key, int size) {

		List<Bot> bots = contestService.getRankingPart(key, 0, size);

		List<RankInfo> rank = new LinkedList<RankInfo>();

		int pos = 0;
		for (Bot bot : bots) {
			rank.add(prepareRankInfo(bot, pos));
			pos++;
		}

		return rank;
	}

	private RankInfo prepareRankInfo(Bot bot, int pos) {
		return new RankInfo(pos, bot.getName(), getUserName(bot.getAuthor()),
				bot.getWins(), bot.getLosses(), bot.getDraws(), bot.getRank(),
				KeyFactory.keyToString(bot.getKey()));
	}

	private RankInfo prepareEmpty(Bot bot, int pos) {
		return new RankInfo(pos, null, null, 0, 0, 0, 0, KeyFactory
				.keyToString(bot.getKey()));
	}

	private String getUserName(Key key) {
		try {
			Account user = accountService.getByKey(key);
			return user.getName();
		} catch (JDOObjectNotFoundException e) {
			return "-not-found-";
		}
	}

	private Contest getContest(Key key) {
		try {
			Contest contest = contestService.getByKey(key);
			return contest;
		} catch (JDOObjectNotFoundException e) {
			return null;
		}
	}

}
